﻿
#region Imported Namespaces

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

#endregion

namespace TupleGeo.Emergency.CAP {

  /// <summary>
  /// <para>
  /// The container for all component parts of the alert message.
  /// </para>
  /// <para>
  /// The alert segment provides basic information about the current message:
  /// its purpose, its source and its status, as well as a unique identifier
  /// for the current message and links to any other, related messages.
  /// An alert segment may be used alone for message acknowledgements,
  /// cancellations or other system functions, but most alert segments
  /// will include at least one <see cref="AlertInfo">info</see> segment.
  /// </para>
  /// </summary>
  /// <remarks>
  /// <para>Required.</para>
  /// <para>
  /// In addition to the specified sub elements may
  /// contain one or more <see cref="Info"/> blocks.
  /// </para>
  /// </remarks>
  [SerializableAttribute()]
  [DesignerCategoryAttribute("code")]
  [XmlTypeAttribute(AnonymousType = true, Namespace = "urn:oasis:names:tc:emergency:cap:1.2")]
  [XmlRootAttribute(ElementName = "alert", Namespace = "urn:oasis:names:tc:emergency:cap:1.2", IsNullable = false)]
  [DataContractAttribute(Name = "alert", Namespace = "urn:oasis:names:tc:emergency:cap:1.2")]
  public partial class Alert : EntityBase<Alert> {

    #region Constructors - Destructors

    /// <summary>
    /// Initializes the Alert.
    /// </summary>
    public Alert() {
      this._any = new List<XmlElement>();
      this._info = new List<AlertInfo>();
      //this._code = new List<string>(); // TODO: UNCOMMENT
    }

    #endregion

    #region Public Properties

    private string _messageId;

    /// <summary>
    /// <para>
    /// The identifier of the alert message. A number or <see cref="string"/>
    /// uniquely identifying this message, assigned by the sender.
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: identifier
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>Required.</para>
    /// <para>MUST NOT include spaces, commas, or restricted xml characters.</para>
    [XmlElementAttribute(ElementName = "identifier", Order = 0)]
    [DataMemberAttribute(Name = "identifier", Order = 0)]
    public virtual string MessageId {
      get {
        return this._messageId;
      }
      set {
        if ((this._messageId != null)) {
          if ((_messageId.Equals(value) != true)) {
            this._messageId = value;
            this.OnPropertyChanged("MessageId");
          }
        }
        else {
          this._messageId = value;
          this.OnPropertyChanged("MessageId");
        }
      }
    }

    private string _senderId;

    /// <summary>
    /// <para>
    /// The identifier of the sender of the alert message. Identifies the originator
    /// of this alert. Guaranteed by assigner to be unique globally. May be based on
    /// an Internet domain name.
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: sender
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>Required.</para>
    /// <para>MUST NOT include spaces, commas, or restricted xml characters.</para>
    /// </remarks>
    [XmlElementAttribute(ElementName = "sender", Order = 1)]
    [DataMemberAttribute(Name = "sender", Order = 1)]
    public virtual string SenderId {
      get {
        return this._senderId;
      }
      set {
        if ((this._senderId != null)) {
          if ((_senderId.Equals(value) != true)) {
            this._senderId = value;
            this.OnPropertyChanged("SenderId");
          }
        }
        else {
          this._senderId = value;
          this.OnPropertyChanged("SenderId");
        }
      }
    }

    private DateTime _sentDateTime;

    /// <summary>
    /// <para>
    /// The time and date of the origination of the alert message.
    /// The date and time is represented [dateTime] format.
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: sent
    /// </para>
    /// </summary>
    /// <example>
    /// [dateTime] format: 2002-05-24T16:49:00-07:00 for 24 Mar 2002 at 16:49 PDT.
    /// </example>
    /// <remarks>
    /// Alphabetic timezone designators such as “Z” MUST NOT be used. The timezone
    /// for UTC MUST be represented as "-00:00" or "+00:00".
    /// </remarks>
    [XmlElementAttribute(ElementName = "sent", Order = 2)]
    [DataMemberAttribute(Name = "sent", Order = 2)]
    public virtual DateTime SentDateTime {
      get {
        return this._sentDateTime;
      }
      set {
        if ((_sentDateTime.Equals(value) != true)) {
          this._sentDateTime = value;
          this.OnPropertyChanged("SentDateTime");
        }
      }
    }

    private AlertStatus _messageStatus;

    /// <summary>
    /// <para>
    /// The code denoting the appropriate handling of the alert message.
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: status
    /// </para>
    /// </summary>
    /// See <see cref="AlertStatus"/> enumeration for valid values.
    /// <remarks>Required.</remarks>
    [XmlElementAttribute(ElementName = "status", Order = 3)]
    [DataMemberAttribute(Name = "status", Order = 3)]
    public virtual AlertStatus MessageStatus {
      get {
        return this._messageStatus;
      }
      set {
        if ((_messageStatus.Equals(value) != true)) {
          this._messageStatus = value;
          this.OnPropertyChanged("MessageStatus");
        }
      }
    }

    private AlertMsgType _messageType;

    /// <summary>
    /// <para>
    /// The code denoting the nature of the alert message
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: msgType
    /// </para>
    /// </summary>
    /// See <see cref="AlertMsgType"/> enumeration for valid values.
    /// <remarks>Required.</remarks>
    [XmlElementAttribute(ElementName = "msgType", Order = 4)]
    [DataMemberAttribute(Name = "msgType", Order = 4)]
    public virtual AlertMsgType MessageType {
      get {
        return this._messageType;
      }
      set {
        if ((_messageType.Equals(value) != true)) {
          this._messageType = value;
          this.OnPropertyChanged("MessageType");
        }
      }
    }

    private string _source;

    /// <summary>
    /// <para>
    /// The text identifying the source of the alert message.
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: source
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>Optional.</para>
    /// <para>
    /// The particular source of this alert. E.g. an
    /// operator or a specific device.
    /// </para>
    /// </remarks>
    [XmlElementAttribute(ElementName = "source", Order = 5)]
    [DataMemberAttribute(Name = "source", Order = 5)]
    public virtual string Source {
      get {
        return this._source;
      }
      set {
        if ((this._source != null)) {
          if ((_source.Equals(value) != true)) {
            this._source = value;
            this.OnPropertyChanged("Source");
          }
        }
        else {
          this._source = value;
          this.OnPropertyChanged("Source");
        }
      }
    }

    private AlertScope _scope;

    /// <summary>
    /// <para>
    /// The code denoting the intended distribution of the alert message.
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: scope
    /// </para>
    /// </summary>
    /// See <see cref="AlertScope"/> enumeration for valid values.
    /// <remarks>Required.</remarks>
    [XmlElementAttribute(ElementName = "scope", Order = 6)]
    [DataMemberAttribute(Name = "scope", Order = 6)]
    public virtual AlertScope Scope {
      get {
        return this._scope;
      }
      set {
        if ((_scope.Equals(value) != true)) {
          this._scope = value;
          this.OnPropertyChanged("Scope");
        }
      }
    }

    private string _restriction;

    /// <summary>
    /// <para>
    /// The text describing the rule for limiting
    /// distribution of the restricted alert message.
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: restriction
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>Conditional.</para>
    /// <para>Used when <see cref="Scope"/> value is "Restricted".</para>
    /// </remarks>
    [XmlElementAttribute(ElementName = "restriction", Order = 7)]
    [DataMemberAttribute(Name = "restriction", Order = 7)]
    public virtual string Restriction {
      get {
        return this._restriction;
      }
      set {
        if ((this._restriction != null)) {
          if ((_restriction.Equals(value) != true)) {
            this._restriction = value;
            this.OnPropertyChanged("Restriction");
          }
        }
        else {
          this._restriction = value;
          this.OnPropertyChanged("Restriction");
        }
      }
    }

    private string _addresses;

    /// <summary>
    /// <para>
    /// The group listing of intended recipients
    /// of the private alert message.
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: addresses
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>Conditional.</para>
    /// <para>
    /// Used when <see cref="Scope"/> value is "Private".
    /// Each recipient SHALL be identified by an identifier or an address.
    /// Multiple space-delimited addresses MAY be included. Addresses
    /// including whitespace MUST be enclosed in double-quotes.
    /// </para> 
    /// </remarks>
    [XmlElementAttribute(ElementName = "addresses", Order = 8)]
    [DataMemberAttribute(Name = "addresses", Order = 8)]
    public virtual string Addresses {
      get {
        return this._addresses;
      }
      set {
        if ((this._addresses != null)) {
          if ((_addresses.Equals(value) != true)) {
            this._addresses = value;
            this.OnPropertyChanged("Addresses");
          }
        }
        else {
          this._addresses = value;
          this.OnPropertyChanged("Addresses");
        }
      }
    }

    private List<string> _handlingCode;

    /// <summary>
    /// <para>
    /// The code denoting the special handling of the alert message.
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: code
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>Optional.</para>
    /// <para>
    /// Any user-defined flag or special code used to flag
    /// the alert message fr special handling. Multiple instances MAY
    /// occur within a single <see cref="Info"/> block.
    /// </para>
    /// </remarks>
    [XmlElementAttribute(ElementName = "code", Order = 9)]
    [DataMemberAttribute(Name = "code", Order = 9)]
    public virtual List<string> HandlingCode {
      get {
        return this._handlingCode;
      }
      set {
        if ((this._handlingCode != null)) {
          if ((_handlingCode.Equals(value) != true)) {
            this._handlingCode = value;
            this.OnPropertyChanged("HandlingCode");
          }
        }
        else {
          this._handlingCode = value;
          this.OnPropertyChanged("HandlingCode");
        }
      }
    }

    private string _note;

    /// <summary>
    /// <para>
    /// The text describing the purpose or
    /// significance of the alert message.
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: note
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>Optional.</para>
    /// <para>
    /// The message note is primarily intended
    /// for use with Cancel and Error alert message.
    /// </para>
    /// </remarks>
    [XmlElementAttribute(ElementName = "note", Order = 10)]
    [DataMemberAttribute(Name = "note", Order = 10)]
    public virtual string Note {
      get {
        return this._note;
      }
      set {
        if ((this._note != null)) {
          if ((_note.Equals(value) != true)) {
            this._note = value;
            this.OnPropertyChanged("Note");
          }
        }
        else {
          this._note = value;
          this.OnPropertyChanged("Note");
        }
      }
    }

    private string _referenceIds;

    /// <summary>
    /// <para>
    /// The group listing identifying earlier
    /// message(s) referenced by the alert message.
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: references
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>Optional.</para>
    /// <para>
    /// The extended message identifier(s) (in the form
    /// <see cref="Sender"/>, <see cref="Identifier"/>, <see cref="Sent"/>)
    /// of an earlier CAP message or messages referenced by this one.
    /// If multiple messages are referenced, they SHALL be separated by
    /// whitespace.
    /// </para>
    /// </remarks>
    [XmlElementAttribute(ElementName = "references", Order = 11)]
    [DataMemberAttribute(Name = "references", Order = 11)]
    public virtual string ReferenceIds {
      get {
        return this._referenceIds;
      }
      set {
        if ((this._referenceIds != null)) {
          if ((_referenceIds.Equals(value) != true)) {
            this._referenceIds = value;
            this.OnPropertyChanged("ReferenceIds");
          }
        }
        else {
          this._referenceIds = value;
          this.OnPropertyChanged("ReferenceIds");
        }
      }
    }

    private string _incidentIds;

    /// <summary>
    /// <para>
    /// The group listing naming the referent
    /// incident(s) of the alert message.
    /// </para>
    /// <para>
    /// Xml serialization: Element, Name: incidents
    /// </para>
    /// </summary>
    /// <remarks>
    /// <para>Optional.</para>
    /// <para>
    /// Used to collate multiple messages referring to
    /// different aspects of the same incident. If multiple incident
    /// identifiers are referenced, they SHALL be separated by
    /// whitespace. Incident names including whitespace SHALL be
    /// surrounded by double-quotes.
    /// </para>
    /// </remarks>
    [XmlElementAttribute(ElementName = "incidents", Order = 12)]
    [DataMemberAttribute(Name = "incidents", Order = 12)]
    public virtual string IncidentIds {
      get {
        return this._incidentIds;
      }
      set {
        if ((this._incidentIds != null)) {
          if ((_incidentIds.Equals(value) != true)) {
            this._incidentIds = value;
            this.OnPropertyChanged("IncidentIds");
          }
        }
        else {
          this._incidentIds = value;
          this.OnPropertyChanged("IncidentIds");
        }
      }
    }

    private List<AlertInfo> _info;

    /// <summary>
    /// TODO !!!
    /// <para>
    /// Xml serialization: Element, Name: info
    /// </para>
    /// </summary>
    [XmlElementAttribute(ElementName = "info", Order = 13)]
    [DataMemberAttribute(Name = "info", Order = 13)]
    public virtual List<AlertInfo> Info {
      get {
        return this._info;
      }
      set {
        if ((this._info != null)) {
          if ((_info.Equals(value) != true)) {
            this._info = value;
            this.OnPropertyChanged("Info");
          }
        }
        else {
          this._info = value;
          this.OnPropertyChanged("Info");
        }
      }
    }

    private List<XmlElement> _any; // TODO: Inserted in 1.2
    
    /// <summary>
    /// TODO !!!
    /// </summary>
    [XmlAnyElementAttribute(Namespace = "http://www.w3.org/2000/09/xmldsig#", Order = 14)]
    [DataMemberAttribute(Name = "Any", Order = 14)]
    public virtual List<XmlElement> Any {
      get {
        return this._any;
      }
      set {
        if ((this._any != null)) {
          if ((_any.Equals(value) != true)) {
            this._any = value;
            this.OnPropertyChanged("Any");
          }
        }
        else {
          this._any = value;
          this.OnPropertyChanged("Any");
        }
      }
    }

    #endregion

  }

}
